package org.budo.dubbo.protocol.http.dispatcher.websocket;

import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.budo.dubbo.protocol.http.BudoDubboHttpProtocol;
import org.budo.dubbo.protocol.http.dispatcher.DispatcherSupport;
import org.budo.dubbo.protocol.http.invocation.BudoDubboRpcInvocation;
import org.budo.dubbo.protocol.http.invocation.adapter.InvocationAdapter;
import org.budo.dubbo.protocol.http.invocation.adapter.ProtocolResponse;
import org.budo.support.slf4j.Slf4j;
import org.slf4j.Logger;

import com.alibaba.dubbo.rpc.Exporter;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcResult;

/**
 * @author li
 * 
 */
@ServerEndpoint("/ws")
public class WebSocketServerEndpoint extends DispatcherSupport {
    private static final Logger log = Slf4j.getLogger();

    @OnMessage
    public void onMessage(String message, Session session) {
        WebSocketProtocolRequest protocolRequest = new WebSocketProtocolRequest(message);

        InvocationAdapter invocationAdapter = this.getInvocationAdapter();
        BudoDubboRpcInvocation invocation;
        try {
            invocation = this.adaptInvocation(invocationAdapter, protocolRequest);
        } catch (Throwable e) {
            log.error("#37 adaptInvocation error, e=" + e); // TODO 应该走 ViewRender
            ProtocolResponse protocolResponse = new WebSocketProtocolResponse(session);
            this.renderInvokeResult(protocolRequest, protocolResponse, new RpcResult(e));
            return;
        }

        BudoDubboHttpProtocol protocol = BudoDubboHttpProtocol.getInstance();
        Exporter<?> exporter = this.findInterfaceExporter(invocation, protocol);

        if (null == exporter) {
            log.error("#41 message=" + message + ", invocation=" + invocation + ", exporter=" + exporter);
            return;
        }

        Invoker<?> invoker = exporter.getInvoker();
        Result result = invoker.invoke(invocation);

        ProtocolResponse protocolResponse = new WebSocketProtocolResponse(session);
        this.renderInvokeResult(protocolRequest, protocolResponse, result);
    }
}

// Object container = Mvcs.getServletContextAttribute("javax.websocket.server.ServerContainer");
// ServerContainer serverContainer = (ServerContainer) container;
// ServerEndpointConfig endpointConfig = ServerEndpointConfig.Builder.create(BudoWebSocketEndpoint.class, "/sss").build();
// serverContainer.addEndpoint(endpointConfig);